/**
 * 210824：升级修改【three.js r120-r131】
 */

let THREE=require('three');
import PrimitiveCompute from './primitive-compute';

let _v= {
    vec30: new THREE.Vector3(),
    vec31: new THREE.Vector3(),
    vec32: new THREE.Vector3(),
    vec33: new THREE.Vector3(),
    vec34: new THREE.Vector3(),
    vec35: new THREE.Vector3(),
    vec36: new THREE.Vector3(),
    vec37: new THREE.Vector3(),
    mat4: new THREE.Matrix4(),
};
const transformArray=(ori,mat,inv,out,temp=new THREE.Vector3())=>{
    for(let i=0;i<ori.length/3;i++){
        temp.set(ori[i*3],ori[i*3+1],ori[i*3+2]).applyMatrix4(mat).applyMatrix4(inv);
        out[i*3]=temp.x;
        out[i*3+1]=temp.y;
        out[i*3+2]=temp.z;
    }
    return out;
};

let ColliderMethods={
    /**
     * 有向有界箱之间是否相交
     * @param box0
     * @param box1
     * @returns {boolean}
     */
    obb_obb:(box0, box1)=>{
        let extents0=box0.extents;
        let transform0=box0.matrixWorld;
        let extents1=box1.extents;
        let transform1=box1.matrixWorld;

        return PrimitiveCompute.obbIntersectsObb(extents0,transform0,extents1,transform1);
    },
    /**
     * 球与球是否相交
     * @param sphere0
     * @param sphere1
     * @param pointOnA
     * @param pointOnB
     * @returns {boolean}
     */
    sphere_sphere:(sphere0,sphere1,pointOnA,pointOnB)=>{
        let r0=sphere0.radius*sphere0.matrixWorld.getMaxScaleOnAxis();
        let r1=sphere1.radius*sphere1.matrixWorld.getMaxScaleOnAxis();
        let rs=r0+r1;
        let c0=sphere0.center;
        let c1=sphere1.center;
        let dir=_v.vec30;
        dir.subVectors(c1,c0).normalize();
        pointOnA.copy(c0).add(dir);
        pointOnB.copy(c1).sub(dir);
        return c0.distanceToSquared(c1)<=(rs*rs);
    },
    /**
     * 有向有界箱与球是否相交
     * @param box
     * @param sphere
     * @returns {boolean}
     */
    obb_sphere:(box,sphere)=>{
        // let c=sphere.center.applyMatrix4(_v.mat4.getInverse(box.matrixWorld));20210824
        let c=sphere.center.applyMatrix4(_v.mat4.copy(box.matrixWorld).invert());
        let r=sphere.radius*sphere.matrixWorld.getMaxScaleOnAxis();
        let dSq=PrimitiveCompute.pointDistanceToAabb(c,box.extents);
        return dSq<=(r*r);
    },
    /**
     * 胶囊之间是否相交
     * @param capsule0
     * @param capsule1
     * @param pointOnA
     * @param pointOnB
     * @returns {boolean}
     */
    capsule_capsule:(capsule0,capsule1,pointOnA,pointOnB)=>{
        let start0=capsule0.bottomCenter.applyMatrix4(capsule0.matrixWorld);
        let end0=capsule0.topCenter.applyMatrix4(capsule0.matrixWorld);
        let start1=capsule1.bottomCenter.applyMatrix4(capsule1.matrixWorld);
        let end1=capsule1.topCenter.applyMatrix4(capsule1.matrixWorld);
        let dSq=PrimitiveCompute.segmentDistanceToSegment(start0,end0,start1,end1,pointOnA,pointOnB);
        let r0=capsule0.radius*capsule0.matrixWorld.getMaxScaleOnAxis();
        let r1=capsule1.radius*capsule1.matrixWorld.getMaxScaleOnAxis();
        let dir=_v.vec30.subVectors(pointOnB,pointOnA).normalize();
        pointOnA.add(_v.vec31.copy(dir).multiplyScalar(r0));
        pointOnB.sub(_v.vec31.copy(dir).multiplyScalar(r1));
        let r=r0+r1;
        return dSq<(r*r);
    },
    /**
     * 有向有界箱与胶囊是否相交
     * @param box
     * @param capsule
     * @returns {boolean}
     */
    obb_capsule:(box,capsule)=>{
        // _v.mat4.getInverse(box.matrixWorld);20210824
        _v.mat4.copy(box.matrixWorld).invert();
        let start=_v.vec31.copy(capsule.bottomCenter.applyMatrix4(capsule.matrixWorld)).applyMatrix4(_v.mat4);
        let end=_v.vec32.copy(capsule.topCenter.applyMatrix4(capsule.matrixWorld)).applyMatrix4(_v.mat4);
        let r=capsule.radius*capsule.matrixWorld.getMaxScaleOnAxis();
        let dSq=PrimitiveCompute.segDistanceToAabb(start,end,box.extents);
        return dSq<r*r;
    },
    /**
     * 球与胶囊是否相交
     * @param sphere
     * @param capsule
     * @param pointOnA
     * @param pointOnB
     * @returns {boolean}
     */
    sphere_capsule:(sphere,capsule,pointOnA,pointOnB)=>{
        let point=sphere.center;
        let start=capsule.bottomCenter.applyMatrix4(capsule.matrixWorld);
        let end=capsule.topCenter.applyMatrix4(capsule.matrixWorld);
        let r0=sphere.radius*sphere.matrixWorld.getMaxScaleOnAxis();
        let r1=capsule.radius*capsule.matrixWorld.getMaxScaleOnAxis();
        let r=r0+r1;
        let d=PrimitiveCompute.pointDistanceToSeg(point,start,end,pointOnB);
        pointOnA.copy(point);
        let dir=_v.vec30.subVectors(pointOnB,pointOnA).normalize();
        pointOnA.add(_v.vec31.copy(dir).multiplyScalar(r0));
        pointOnB.sub(_v.vec31.copy(dir).multiplyScalar(r1));
        return d<(r*r);
    },
    /**
     * 凸包（2D点集）与凸包（2D点集）
     * @param boxScn0
     * @param boxScn1
     */
    boxScn_boxScn:(boxScn0,boxScn1)=>{
        let convex0=boxScn0.outer;
        let convex1=boxScn1.outer;
        let convex0IntConvex1= PrimitiveCompute.convex2DIntersectsToConvex2D(convex0,convex1);
        let convex1IntConvex0= PrimitiveCompute.convex2DIntersectsToConvex2D(convex1,convex0);
        return convex0IntConvex1&&convex1IntConvex0;
    },
    /**
     * 凸壳（点集）与凸壳（点集）
     * @param convex0
     * @param convex1
     * @param pointOnA
     * @param pointOnB
     * @returns {*|boolean}
     */
    convex_convex:(convex0,convex1,pointOnA,pointOnB)=>{
        // let inv=_v.mat4.getInverse(convex1.matrixWorld);20210824
        let inv=_v.mat4.copy(convex1.matrixWorld).invert();
        let mat=convex0.matrixWorld;
        let vs0=transformArray(convex0.vertices,mat,inv,[],_v.vec30);
        let vs1=convex1.vertices;
        let intersect= PrimitiveCompute.convexIntersectsConvexSeparationAxisFixed(vs0,vs1,pointOnA,pointOnB);
        pointOnA.applyMatrix4(convex1.matrixWorld);
        pointOnB.applyMatrix4(convex1.matrixWorld);
        return intersect;
    },
    /**
     * 凸壳（点集）与有向有界箱（转换为凸壳检测）
     * @param convex
     * @param box
     * @param pointOnA
     * @param pointOnB
     * @returns {*|boolean}
     */
    convex_obb:(convex,box,pointOnA,pointOnB)=>{
        // let inv=_v.mat4.getInverse(convex.matrixWorld);20210824
        let inv=_v.mat4.copy(convex.matrixWorld).invert();
        let mat=box.matrixWorld;
        let vs0=convex.vertices;
        let x=box.extents[0];
        let y=box.extents[1];
        let z=box.extents[2];
        let bvs=[-x,-y,z,x,-y,z,x,-y,-z,-x,-y,-z,-x,y,z,x,y,z,x,y,-z,-x,y,-z];
        bvs=transformArray(bvs,mat,inv,[],_v.vec30);
        let intersect=PrimitiveCompute.convexIntersectsConvexSeparationAxisFixed(vs0,bvs,pointOnA,pointOnB);
        pointOnA.applyMatrix4(convex.matrixWorld);
        pointOnB.applyMatrix4(convex.matrixWorld);
        return intersect;
    },
    /**
     * 凸壳（点集）与球
     * @param convex
     * @param sphere
     * @param pointOnA
     * @param pointOnB
     * @returns {*|boolean}
     */
    convex_sphere:(convex,sphere,pointOnA,pointOnB)=>{
        // let inv=_v.mat4.getInverse(convex.matrixWorld);20210824
        let inv=_v.mat4.copy(convex.matrixWorld).invert();
        let vs=convex.vertices;
        let sphereCenter=_v.vec30.copy(sphere.center).applyMatrix4(inv);
        let sphereRadius=sphere.radius*sphere.matrixWorld.getMaxScaleOnAxis()*inv.getMaxScaleOnAxis();
        let intersect=PrimitiveCompute.convexIntersectsSphere(vs,[sphereCenter.x,sphereCenter.y,sphereCenter.z,sphereRadius],pointOnA,pointOnB);
        pointOnA.applyMatrix4(convex.matrixWorld);
        pointOnB.applyMatrix4(convex.matrixWorld);
        return intersect;
    },
    /**
     * 凸壳（点集）与胶囊体
     * @param convex
     * @param capsule
     * @param pointOnA
     * @param pointOnB
     * @returns {*|void}
     */
    convex_capsule:(convex,capsule,pointOnA,pointOnB)=>{
        // let inv=_v.mat4.getInverse(convex.matrixWorld);20210824
        let inv=_v.mat4.copy(convex.matrixWorld).invert();
        let mat=capsule.matrixWorld;
        let vs=convex.vertices;
        let tCenter=capsule.topCenter.applyMatrix4(mat).applyMatrix4(inv);
        let bCenter=capsule.bottomCenter.applyMatrix4(mat).applyMatrix4(inv);
        let radius=capsule.radius*mat.getMaxScaleOnAxis()*inv.getMaxScaleOnAxis();
        let intersect=PrimitiveCompute.convexIntersectsCapsule(vs,[tCenter.x,tCenter.y,tCenter.z,bCenter.x,bCenter.y,bCenter.z,radius],pointOnA,pointOnB);
        pointOnA.applyMatrix4(convex.matrixWorld);
        pointOnB.applyMatrix4(convex.matrixWorld);
        return intersect;
    },
};

export default ColliderMethods;